
#include "ShaderCamera.h"

ShaderCamera::ShaderCamera()
{

}

void ShaderCamera::release()
{

}

void ShaderCamera::init()
{
	for (int i = (int)NONE + 1; i < (int)COUNT; i++)
	{
		auto cAction = std::make_shared<CameraAction>();
		m_mapCameraAction.insert(std::pair<ActionEnum, CameraActionPtr>((ActionEnum)i, cAction));
	}

	m_cameraPos = glm::vec3(0.0f, 0.0f, 5.0f);
}

glm::mat4 ShaderCamera::getLookAt()
{
	return glm::lookAt(getCameraPos(), getCameraPos() + getCameraFront(), getCameraUp());
}

glm::vec3 ShaderCamera::getCameraPos()
{
	//GLfloat radius = 10.0f;
	//GLfloat camX = sin(glfwGetTime()) * radius;
	//GLfloat camZ = cos(glfwGetTime()) * radius;
	//return glm::vec3(camX, 0.0f, camZ);
	return m_cameraPos;
}

glm::vec3 ShaderCamera::getCameraFront()
{
	return glm::vec3(0.0f, 0.0f, -1.0f);
}

glm::vec3 ShaderCamera::getCameraUp()
{
	return glm::vec3(0.0f, 1.0f, 0.0f);
}

void ShaderCamera::setCameraActionWithkeyBoard(int key, int modes, bool isPress)
{
	auto action = NONE;
	switch (key)
	{
	case GLFW_KEY_W:
		action = FORWARD;
		break;
	case GLFW_KEY_S:
		action = RETREAT;
		break;
	case GLFW_KEY_A:
		action = LEFT;
		break;
	case GLFW_KEY_D:
		action = RIGHT;
		break;
	case GLFW_KEY_J:
		action = UP;
		break;
	case GLFW_KEY_K:
		action = DOWN;
	}
	if (action != NONE)
	{
		auto it = m_mapCameraAction.find(action);
		if (it != m_mapCameraAction.end())
		{
			(*it).second->setTrigger(isPress);
		}
	}
}

void ShaderCamera::update(float dt)
{
	glm::vec3 cameraFront = getCameraFront();
	glm::vec3 cameraUp = getCameraUp();
	std::for_each(m_mapCameraAction.begin(), m_mapCameraAction.end(), [this, dt, cameraFront, cameraUp](const std::pair<ActionEnum, CameraActionPtr>& pair)
	{
		bool isTrigger = pair.second->getTrigger();
		if (isTrigger)
		{
			float speed = pair.second->getSpeed() * dt;
			switch (pair.first)
			{
			case FORWARD:
				this->m_cameraPos += speed * cameraFront;
				break;
			case RETREAT:
				this->m_cameraPos -= speed * cameraFront;
				break;
			case LEFT:
				this->m_cameraPos -= glm::normalize(glm::cross(cameraFront, cameraUp)) * speed;
				break;
			case RIGHT:
				this->m_cameraPos += glm::normalize(glm::cross(cameraFront, cameraUp)) * speed;
				break;
			case UP:
				this->m_cameraPos += speed * cameraUp;
				break;
			case DOWN:
				this->m_cameraPos -= speed * cameraUp;
				break;
			}
		}

	});
}